package com.superview.power;

import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**   * Socket套接字工厂，对外接口是静态方法 SocketFactory.request(String, String, String, int)
 *     * @author chao    
 *     */
public class  SocketFactory {
	
	private Socket socket = null;    
	private String targetIpAddress = null;    
	private int targetPort = 0;    
	private static SocketFactory sf = new SocketFactory();    
	
	

	public String getTargetIpAddress() {
		return targetIpAddress;
	}

	public void setTargetIpAddress(String targetIpAddress) {
		this.targetIpAddress = targetIpAddress;
	}

	public int getTargetPort() {
		return targetPort;
	}

	public void setTargetPort(int targetPort) {
		this.targetPort = targetPort;
	}



	public SocketFactory() {        
		
	}   
	
	/**       * 建立一条TCP/IP连接
	 *        * @param targetIpAddress String 目标ip地址
	 *        * @param targetPort String 目标端口       
	 *        * @throws IOException       
	 *        */
	synchronized private void connect(String targetIpAddress, int targetPort) throws IOException {
		setTargetIpAddress(targetIpAddress);            
		setTargetPort(targetPort);    
		if(socket == null)                
			socket = new Socket(targetIpAddress, targetPort);        
	}
	
	
	/**       
	 * * 这是对外接口。发送命令，接收反馈和接收message放两个线程，       
	 * * 发送命令并接收反馈是短连接，所以每次执行成功后，将销毁socket并终止线程，       
	 * * 接收message是长连接，所以可能会new出n个线程，建议对接收message的线程做缓存       
	 * * @param commandType String 命令类型       
	 * * @param commandContent String 命令内容       
	 * * @param targetIP String 目标ip       
	 * * @param targetPort int 目标端口       
	 * */
	synchronized public static void request(byte cmdCode,byte output) {    
//		if (commandType.equalsIgnoreCase(MessageFactory.SCAN_COMMAND)) {                
//			sf.new GetMessageSocketThread(commandType, commandContent, targetIP, targetPort);     
//		} else {                
//			sf.new RequestSocketThread(commandType, commandContent, targetIP, targetPort);            
//		}        
	
			
			sf.new RequestSocketThread(new CmdFactory(cmdCode,output));  
		
		 
	}    
	
	/**       * 发送请求       
	 * * @param commandType String 命令类型       
	 * * @param commandContent String 命令内容       
	 * * @param targetIp String 目标ip       
	 * */
	synchronized private void sendRequest(CmdFactory cf) {            
		OutputStream os = null;            
		BufferedOutputStream bs = null;    
		try {                
			os = socket.getOutputStream();                
			bs = new BufferedOutputStream(os);    
			////////////////////////////////////////
//			char[] message = MessageFactory.makeRequestMessage(targetIp, commandType, commandContent, MessageFactory.COMMAND_TRADE_CODE, MessageFactory.RIGHT_COMMAND, MessageFactory.MESSAGE_END_FLAG);    
//			for (int i = 0; i < message.length; i++)                    
//				bs.write(new String(message).getBytes(), i, 1);       
			///////////////////////////////////////////	
			
			byte[] message = cf.getRequestMessage();
			//System.out.println(message);
			//0x3,0x25,0x0,0x0,0x5,0x0,0x0,0x8,0x2,0x0,0x0,0x0
			byte[] ms = new byte[12];

			//System.out.println();
			System.out.print("write start: "+cf.getTempOutput());
			bs.write(message); 
			bs.flush();        
			System.out.print("write end: "+cf.getTempOutput());
			//System.out.println("end");
			//SwingUtils.appendLog(MainForm.jTextArea, "发送请求：'" + commandType + "' '" + commandContent + "' '" + targetIp + "'", ReadConfig.commandStateShowLineCount);            
		} catch (IOException e) {                
			//SwingUtils.appendLog(MainForm.jTextArea, "Error!!! 发送请求：'" + commandType + "' '" + commandContent + "' '" + targetIp + "'失败！！ " + e.getMessage(), ReadConfig.commandStateShowLineCount);                
			e.printStackTrace();            
		} catch (Exception e) {                
			e.printStackTrace();            
		} finally {            
				
		}        
	}    
	
	
	/**       * 获得反馈       *        
	 * * @return 如果成功获得反馈，则返回true；否则返回false       
	 * */
	synchronized private boolean getResponse() {            
		InputStream is = null;            
		DataInputStream di = null;    
		boolean returnFlag = false;    
		try {                
			is = socket.getInputStream();                
			di = new DataInputStream(is);    
			byte[] temp = new byte[1];    
			int flag = 0;                
			ArrayList tempByteList = new ArrayList();    
			int i = 0;    
			while (flag != -1) {                    
				i++;                    
				flag = di.read(temp = new byte[1]);    
				if (flag != -1)                        
					tempByteList.add(temp);    
//				if (i == 38)    
//					break;                
			}
			//System.out.println("tempByteList.size()"+tempByteList.size());
			if (i == 1) {                    
				
				return false;                
			}  
			
			//System.out.println();
			               
			//SwingUtils.appendLog(MainForm.jTextArea, "收到 response", ReadConfig.comman  
		} catch (IOException e) {                
			e.printStackTrace();            
		} finally {            
			
		}    
		return returnFlag;        
	}    
	
	/**       
	 * * 负责发送请求接收反馈的内部线程类，每new一个RequestSocketThread线程，       
	 * * 就new一个socket，建立一条专属连接，成功接收反馈后将销毁socket，终止线程。       
	 * * 将发送请求，接收反馈放进内部线程处理，是为了防止套接字阻塞造成主线程挂死。       
	 * * @author cuishen       
	 * * @version 1.2       
	 * */
	class RequestSocketThread implements Runnable {    
		 private SocketFactory socketFactory;    
		// private String commandType = null;    
		// private String commandContent = null;    
		// private String targetIP = null;       
		 private CmdFactory cf = null;
		 Thread t;      
		 
		 public RequestSocketThread(CmdFactory cf) {
			 this.cf=cf;
			 this.socketFactory = new SocketFactory();    
			 try {    
				 this.socketFactory.connect("192.168.1.250", 2000);
			 } catch (UnknownHostException e) {                    
				 //SwingUtils.Error("主机 IP 地址无法确定,无法建立连接！ targetIP=" + ReadConfig.targetIpAddress + ", targetPort=" + ReadConfig.targetPort);                    
				 e.printStackTrace();                
			 } catch (IOException e) {                    
				 //SwingUtils.Error("访问被拒绝，无法建立连接，请检查网络！ targetIP=" + ReadConfig.targetIpAddress + ", targetPort=" + ReadConfig.targetPort);                    
				 e.printStackTrace();                
			 }    
//			 this.commandType = commandType;    
//			 this.commandContent = commandContent;    
//			 this.targetIP = targetIP;                
			 t = new Thread(this);                
			 t.start();            
		 }
		 
		 synchronized  public void run() {  
			 	ReentrantReadWriteLock rwl= new ReentrantReadWriteLock();
			 	
			 	rwl.writeLock().lock();
			 	System.out.println("output "+cf.getTempOutput());
				 this.socketFactory.sendRequest(cf);    
//				 this.socketFactory.getResponse();  
	
					System.out.print("end "+cf.getTempOutput());
					System.out.println(" ####索引号="+cf.getTempCmdIndex());
					stopThread();  
					
				 rwl.writeLock().unlock();
				 
			  
		 }      
		 
		 synchronized public void   stopThread() {    
			 try {    
//				 this.commandType = null;    
//				 this.commandContent = null;    
//				 this.targetIP = null;  
				 cf = null;
				 socketFactory.closeSocket();                    
				 socketFactory = null;  
				 
				 this.t.join(1000);                
			 } 
			 catch (InterruptedException e) {                    
					 e.printStackTrace();                
			 } 
			 finally {                    
					 t = null;                
			 }            
		 }        
	 }  
	

	/**       * 关闭套接字       */
	synchronized private void  closeSocket() {    
		try {    
			if (!socket.isClosed())                    
				socket.close();                
			socket = null;            
		} catch (IOException e) {                
			e.printStackTrace();            
		}        
	}    
	
	
	public static void main( String[] args){
		//SocketFactory.request();
		SocketFactory.request(CmdFactory.CMD_SET_IO_OUT_VALUE, (byte) 0);
	}
}
